package com.sojson.util.security.shiro.shiromanager.impl;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;

import com.sojson.util.INI4jUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.filter.FilterUtil;
import com.sojson.util.security.shiro.shiromanager.ShiroManager;

import lombok.extern.slf4j.Slf4j;

/**
 * 负责读取shiro的权限列表，目的:将权限列表和shiro.xml分离
 * 
 * @author liu
 *
 */
@Slf4j
public class CustomShiroManager implements ShiroManager {

    /** 注意/r/n前不能有空格 */
    private final String CRLF = "\r\n";
    /** 过滤器权限列表在ini文件中的分组 */
    @Value("${so.permission.ini.shiroFilter}")
    private String permissionIniShiroFilter;
    @Resource
    @Autowired
    @Lazy
    public ShiroFilterFactoryBean shiroFilterFactoryBean;

    /**
     * 获取权限列表字符串
     * 
     * @throws IOException
     */
    @Override
    public String loadFilterChainDefinitions() throws IOException {
        System.out.println("CustomShiroManager:loadFilterChainDefinitions");
        StringBuffer sb = new StringBuffer();
        // 固定权限，采用读取配置文件
        sb.append(getFixedAuthRule());
        return sb.toString();
    }

    /**
     * 从配额文件获取权限字符串
     * 
     * @throws IOException
     */
    private String getFixedAuthRule() throws IOException {
        System.out.println("CustomShiroManager:getFixedAuthRule");
        INI4jUtil ini = FilterUtil.getIni4jUtil();
        String section = permissionIniShiroFilter;
        Set<String> keys = ini.get(section).keySet();
        StringBuffer sb = new StringBuffer();
        for (String key : keys) {
            String value = ini.get(section, key);
            if (isNotBlank(value)) {
                sb.append(key).append(" = ").append(value).append(CRLF);
            }
        }

        return sb.toString();
    }

    /**
     * 重新构建权限过滤器 一般在修改了用户角色、用户等信息时，需要再次调用该方法 此方法加同步锁
     * 
     * @throws IOException
     */
    @Override
    public synchronized void reCreateFilterChains() throws IOException {
        System.out.println("CustomShiroManager:reCreateFilterChains");
        AbstractShiroFilter shiroFilter = null;
        try {
            shiroFilter = (AbstractShiroFilter)shiroFilterFactoryBean.getObject();
        } catch (Exception e) {
            log.error("getShiroFilter from shiroFilterFactoryBean error!", e);
            throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
        }

        PathMatchingFilterChainResolver filterChainResolver =
            (PathMatchingFilterChainResolver)shiroFilter.getFilterChainResolver();
        DefaultFilterChainManager manager = (DefaultFilterChainManager)filterChainResolver.getFilterChainManager();

        // 清空老的权限控制
        manager.getFilterChains().clear();

        shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
        shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());
        // 重新构建生成
        Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
        for (Map.Entry<String, String> entry : chains.entrySet()) {
            String url = entry.getKey();
            String chainDefinition = entry.getValue().trim().replace(" ", "");
            manager.createChain(url, chainDefinition);
        }

    }

    /**
     * 判断一个字符串是否不是空
     * 
     * @param obj
     * @return
     */
    private boolean isNotBlank(String str) {
        return StringUtil.isNotBlank(str);
    }

}